package circlequeue

import (
	"errors"
	"fmt"
)

//Object 数据结构
type Object interface{}

// len 表示我们用于存储数据的数组的长度
var len int

/*
Queue 队列
*/
type Queue struct {
	data []Object
	head int
	tail int
}

// InitCircleQueue 队列初始化操作
func InitCircleQueue(size int) Queue {
	len = size + 1
	array := make([]Object, len)
	q := Queue{}
	q.data = array
	q.head = 0
	q.tail = 0
	return q
}

/*
Empty 判断是否为空
*/
func (q *Queue) Empty() bool {
	if q.head == q.tail {
		return true
	}
	return false
}

/*
Full 判断是否已满
*/
func (q *Queue) Full() bool {
	next := q.tailNext()
	if next == q.head {
		return true
	}
	return false
}

//next 获取下一个元素的下标
func (q *Queue) tailNext() int {
	var next int

	if q.tail == len-1 {
		//当tail 位于最后一个元素时, next  = 0
		next = 0
	} else {
		next = q.tail + 1
	}
	return next
}

// Push  从尾部添加元素添加元素
func (q *Queue) Push(data Object) (err error) {
	// head 所处的下标先添加元素, 然后, head 下标 + 1
	curr := q.tail
	if q.Full() {
		fmt.Println("队列已满, 无法继续添加")
		return errors.New("队列已满, 无法继续添加")
	}
	q.data[curr] = data
	// //head 下标向后移动
	if q.tail == len-1 {
		q.tail = 0
	} else {
		q.tail++
	}
	fmt.Println("添加元素成功:", data)
	return nil
}

// Pop 从头部弹出元素
func (q *Queue) Pop() (data Object) {
	if q.Empty() {
		fmt.Println("队列为空, 无法继续弹出")
		return nil
	}
	first := q.head
	// 头元素下标后移
	if q.head == len-1 {
		q.head = 0
	} else {
		q.head++
	}
	data = q.data[first]
	//元素拿出后, q.data 中对应下标的值 设定为null
	q.data[first] = nil
	fmt.Println("弹出元素:", data)
	return data
}

// ShowAll q.data下标从0开始, 展示到最后一个元素, 用于观察队列是否循环
func (q *Queue) ShowAll() {
	for index := 0; index < len; index++ {
		item := q.data[index]
		fmt.Printf("下标为%d的元素为%v \n", index, item)
	}
}
